// Damn maybe this is std stuff
//#[allow(unused)]
//#[allow(dead_code)

#![no_main]
#![no_std]

use core::ffi::{c_char, c_int, c_void};
use core::mem::zeroed;
use core::panic::PanicInfo;

#[panic_handler]
unsafe fn panic(_info: &PanicInfo) -> ! {
    loop {}
}

extern "C" {
    fn printf(fmt: *const u8, ...) -> c_int;
    fn exit(status: i32) -> !;
    fn realloc(ptr: *mut c_void, size: usize) -> *mut c_void;
    fn free(ptr: *mut c_void);
}

// TODO: no std dynamic array
#[repr(C)]
struct Array<T> {
    items: *mut T,
    count: usize,
    capacity: usize,
}

impl<T> Array<T> {
    unsafe fn new() -> Self {
        Self {
            items: core::ptr::null_mut(),
            count: 0,
            capacity: 0,
        }
    }
}

// push an element into dynamic array
unsafe fn array_push<T>(xs: *mut Array<T>, item: T) {
    if (*xs).count >= (*xs).capacity {
        if (*xs).capacity == 0 {
            (*xs).capacity = 256;
        } else {
            (*xs).capacity *= 2;
        }

        // realloc require c runtime init
        // tsoding video
        (*xs).items =
            realloc((*xs).items as *mut c_void, size_of::<T>() * (*xs).capacity) as *mut T;
    }

    *((*xs).items.add((*xs).count)) = item;
    (*xs).count += 1;
}


unsafe fn array_free<T>(xs: *mut Array<T>) {
    free((*xs).items as *mut c_void);
    (*xs).items = core::ptr::null_mut();
    (*xs).count = 0;
    (*xs).capacity = 0;
}


// You have to no mangle
// this kind of shit thing
#[no_mangle]
unsafe extern "C" fn main() {
    // printf(b"Hello world\n".as_ptr());
    // TODO: next we are doing dynamic array
    // let xs: Vec<i32> = Vec::new();// Error: since std stuff

    let mut xs: Array<i32> = Array::new();
    array_push(&mut xs, 69);
    array_push(&mut xs, 69);
    array_push(&mut xs, 69);
    array_push(&mut xs, 69);
    array_push(&mut xs, 69);
    array_push(&mut xs, 69);
    array_push(&mut xs, 69);

    printf(b"xs.count = %zu\n\0".as_ptr(), xs.count);

    for i in 0..xs.count {
        printf(b"i = %zu, value = %d\n\0".as_ptr(), i, *xs.items.add(i));
    } 

    array_free(&mut xs);


    exit(0);
}
